package com.wmx.controller;

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Servlet HttpSession 与 Cookie & @RequestHeader 获取请求头 与 CookieValue 获取 Cookie 值
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2022/4/10 8:48
 */
@RestController
public class CookieController {

    /**
     * http://localhost:8080/servlet/cookie
     * 设置、获取上一次访问时间(lastAccessTime)
     *
     * @param request
     * @param response
     */
    @GetMapping("servlet/cookie")
    public String servletCookie(HttpServletRequest request, HttpServletResponse response) {
        // 上次访问时间(格式化后的)
        String lastAccessTimeMessage = "-:-:-";

        // Cookie[] getCookies()：获取客户端随此请求发送的所有 Cookie 对象，如果请求没有 Cookie ，则方法返回null.
        // String getName()：返回 cookie 的名称，名称是唯一的，且创建后无法更改。
        // String getValue()：获取 Cookie 的值
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                // lastAccessTime：上次访问时间
                if ("lastAccessTime".equals(cookie.getName()) && !StringUtils.isEmpty(cookie.getValue())) {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    lastAccessTimeMessage = dateFormat.format(new Date(Long.parseLong(cookie.getValue())));
                    break;
                }
            }
        }
        //2）往浏览器发送 Cookie 值。名称一样时，值会自动覆盖.
        Cookie lastAccessTimeCookie = new Cookie("lastAccessTime", Instant.now().toEpochMilli() + "");
        //2.1、设置本 Cookie 失效时间为 30 分钟，30分钟内，即使用户关闭浏览器也不会影响下一次传值进来，因为浏览器会存储到磁盘
        //相反默认未设置失效时间时，默认浏览器关闭时，Cookie 就被清除了，因为只是被存储在浏览器缓存中，只在当前会话内有效
        //cookie.setMaxAge(Integer.MAX_VALUE) 设置超时时间为无限大
        //cookie.setMaxAge(0)：0 表示删除 Cookie
        lastAccessTimeCookie.setMaxAge(30 * 60);

        // 2.2、设置Cookie适用的路径，如果不指定路径或者为空，默认浏览器会将Cookie返回给当前目录及其子孙目录，以及同级目录及其子孙目录。
        // 如下所示表示当前请求下设置的 lastAccessTimeCookie，整个应用下的其它所有请求路径都能获取到 lastAccessTimeCookie 值.
        // 如果应用没有设置请求上下文,则 request.getContextPath() 返回空
        String path = StringUtils.isEmpty(request.getContextPath()) ? "/" : request.getContextPath();
        lastAccessTimeCookie.setPath(path);

        //设置的 Cookie 最好必须发送给客户端才能生效
        response.addCookie(lastAccessTimeCookie);

        return "上次访问时间：" + lastAccessTimeMessage;
    }


    /**
     * http://localhost:8080/servlet/session?key=wangMaoXiong&value=汪茂雄
     * 设置、获取 HttpSession 会话属性
     *
     * @param request
     * @param response
     * @param key
     * @param value
     */
    @GetMapping("servlet/session")
    public Map<String, Object> servletSession(HttpServletRequest request, HttpServletResponse response, @RequestParam String key, @RequestParam String value) {

        // 1、返回与此请求关联的当前会话，或者如果该请求没有会话，则创建一个会话。
        HttpSession httpSession = request.getSession();

        Object sessionAttribute = httpSession.getAttribute(key);
        if (sessionAttribute == null || !sessionAttribute.toString().equals(value)) {
            // 设置会话范围内属性，应用下任意地方,在会话范围内当前会话用户都能取到值.
            httpSession.setAttribute(key, value);
        }

        // 设置会话超时时间(秒)。表示用户此时间内没有访问本系统时，则会话失效。
        // 只要用户访问本应用下的任意资源都是可以的，都能维持会话
        httpSession.setMaxInactiveInterval(60);

        // 2、默认情况下，HttpSession 在浏览器关闭重开再次访问时，因为客户端没有了之前名称为"JSESSIONID"的 Cookie 而创建一个新的会话
        // 所以如果想要用户在重开浏览器的情况下还能维持在一个会话内，就要让会话的 "JSESSIONID" Cookie 不能随浏览器关闭而消失，必须写入磁盘
        Cookie cookie = new Cookie("JSESSIONID", httpSession.getId());
        String path = StringUtils.isEmpty(request.getContextPath()) ? "/" : request.getContextPath();
        cookie.setPath(path);
        cookie.setMaxAge(Integer.MAX_VALUE);
        response.addCookie(cookie);

        String id = httpSession.getId();
        Map<String, Object> map = new HashMap<>(8);
        map.put("sessionId", id);
        map.put("JSESSIONID", cookie.getValue());
        map.put(key, httpSession.getAttribute(key));

        return map;
    }

    /**
     * http://localhost:8080/request/header
     * <p>
     * * @CookieValue 获取 Cookie 值
     * * @RequestHeader 获取请求头信息
     *
     * @param userAgent
     * @return
     */
    @GetMapping("request/header")
    public Map<String, Object> requestHeader(@RequestHeader("User-Agent") String userAgent,
                                             @CookieValue(value = "JSESSIONID", required = false) String jSessionId) {
        Map<String, Object> map = new HashMap<>(8);
        map.put("User-Agent", userAgent);
        map.put("JSESSIONID", jSessionId);
        return map;
    }


}
